`timescale 1ns/1ps

module key_table_tb;

    // 参数
    parameter SM2_KEY_NUM = 5;
    parameter SM4_KEY_NUM = 5;
    parameter MAX_KEY_NUM = (SM2_KEY_NUM > SM4_KEY_NUM) ? SM2_KEY_NUM : SM4_KEY_NUM;
    parameter KEY_INDEX_WIDTH = $clog2(MAX_KEY_NUM);

    // 信号定义
    reg                  clk;
    reg                  rst_n;
    reg                  wr_en;
    reg                  rd_en;
    reg   [1:0]          key_type;
    reg   [KEY_INDEX_WIDTH-1:0] key_index;
    reg   [63:0]         pin;
    reg   [255:0]        key_1_in;
    reg   [255:0]        key_2_in;

    wire  [255:0]        key_1;
    wire  [255:0]        key_2;
    wire                 key_ready;
    wire  [1:0]          state;

    // 实例化
    key_table #(
        .SM2_KEY_NUM(SM2_KEY_NUM),
        .SM4_KEY_NUM(SM4_KEY_NUM)
    ) dut (
        .clk(clk),
        .rst_n(rst_n),
        .wr_en(wr_en),
        .rd_en(rd_en),
        .key_type(key_type),
        .key_index(key_index),
        .pin(pin),
        .key_1_in(key_1_in),
        .key_2_in(key_2_in),
        .key_1(key_1),
        .key_2(key_2),
        .key_ready(key_ready),
        .state(state)
    );

    // 时钟生成
    initial clk = 0;
    always #5 clk = ~clk;

    // 仿真流程
    initial begin
        // 复位
        rst_n = 0;
        wr_en = 0;
        rd_en = 0;
        key_type = 0;
        key_index = 0;
        pin = 0;
        key_1_in = 0;
        key_2_in = 0;
        #20;
        rst_n = 1;
        #20;

        // 写入第一个SM2密钥，PIN=64'h12345678
        wr_en = 1;
        rd_en = 0;
        key_type = 2'b00;
        key_index = 0;
        pin = 64'h12345678;
        key_1_in = 256'hAABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899;
        key_2_in = 256'h00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF;
        #10;
        wr_en = 0;
        #10;

        // 写入第一个SM4密钥，PIN=64'h87654321
        wr_en = 1;
        key_type = 2'b01;
        key_index = 0;
        pin = 64'h87654321;
        key_1_in = {128'd0, 128'hA1B2C3D4E5F60718A9BACBDCEDFE0F10};
        key_2_in = 0;
        #10;
        wr_en = 0;
        #10;

        // 读SM2密钥，PIN正确
        rd_en = 1;
        key_type = 2'b00;
        key_index = 0;
        pin = 64'h12345678;
        #10;
        rd_en = 0;
        #10;

        // 读SM2密钥，PIN错误
        rd_en = 1;
        key_type = 2'b00;
        key_index = 0;
        pin = 64'hDEADBEEF;
        #10;
        rd_en = 0;
        #10;

        // 读SM4密钥，PIN正确
        rd_en = 1;
        key_type = 2'b01;
        key_index = 0;
        pin = 64'h87654321;
        #10;
        rd_en = 0;
        #10;

        // 读SM4密钥，PIN错误
        rd_en = 1;
        key_type = 2'b01;
        key_index = 0;
        pin = 64'hDEADBEEF;
        #10;
        rd_en = 0;
        #10;

        // 读SM2密钥，索引非法
        rd_en = 1;
        key_type = 2'b00;
        key_index = 5; // 超过范围
        pin = 64'h12345678;
        #10;
        rd_en = 0;
        #10;

        // 读SM4密钥，索引非法
        rd_en = 1;
        key_type = 2'b01;
        key_index = 6; // 超过范围
        pin = 64'h87654321;
        #10;
        rd_en = 0;
        #10;

        // 结束仿真
        #20;
        $finish;
    end

    // 输出波形
    initial begin
        $dumpfile("key_table_tb.vcd");
        $dumpvars(0, key_table_tb);
    end

endmodule